#include "main.hh"

ActionQueue* ActionQueue::act_queue_ = 0;

Main::Main (int argc, char** argv, Server* serv)
{
  s = serv;

  go = true;
  player_name = argv[3];

  // 1024 * 768
  w = new Window (1024, 768);
  glutInit (&argc, argv);
  glewInit ();

  //we need to load our models here, after glewInit
  ContentHandler* ch = ContentHandler::get ("content/trans.conf");

  ch->instantiate_texture ("map", "content/map.bmp");
  ch->instantiate_texture ("menu", "content/menu.bmp");

  //  ch->instantiate_mesh (0, "content/sphere.dae");

  c = new CameraRts (Vector3f ((63.0 * (1.0 / w->ratio_get ())) / tan (35 * M_PI / 180),
			       64, 64), w);

  Vector2d center (w->width_get () / 2, w->height_get () / 2);

  //  SDL_ShowCursor (SDL_DISABLE);
  SDL_WarpMouse(center (0), center (1));
  //  SDL_WM_GrabInput (SDL_GRAB_ON);

  // menu building
  mh = new MenuHandler (w);
  // build_menu ();

  // input building
  m = new Mouse (mh, s, c);
  k = new Keyboard (&go, c, m);
  s->disp ()->insert (std::make_pair ((size_t) m, boost::shared_ptr<Displayable> (m)));

  d = new Displayer (w->screen_get (), c);

  //starting receiving request
  s->build_map ();

  listen = boost::thread (&Server::run, s);  

  // interface building
  fps = new TextImg (std::string ("0"), Vector2f (20, 768 - 20));
  interface.push_back (fps);
  // interface.push_back (chat);
  interface.push_back (mh);

  // action handling
  ActionQueue* aq = ActionQueue::Instance ();

  queue_ = aq->queue_get ();

  obj_act_ = new std::map<int, ObjAction*> ();
}

Main::~Main ()
{
  obj_act_->clear ();
  delete obj_act_;
}

void
Main::loop ()
{
  // time information
  int frame = 0;
  double start = SDL_GetTicks ();
  double timer_input = 0;
  float current = start;

  if (s->reset_selection ())
    m->reset_selection ();
  //  std::string tmp;
  //  s->nm ()->send (RType::GET_ALL_OBJECTS, tmp);

  unsigned char* curid = new unsigned char[3];
  curid[0] = 0;
  curid[1] = 0;
  curid[2] = '\0';
  unsigned char* tmpid = new unsigned char[3];
  tmpid[2] = '\0';

  while (!s->nm ()->eh ()->error () && go)
  {
    ++frame;

    if (SDL_GetTicks () - start > 1000)
    {
      start = SDL_GetTicks ();
      std::stringstream ss;
      ss << frame;
      fps->text (std::string (ss.str ()));
      frame = 0;
    }

    // Input treatment
    k->event (SDL_GetTicks () - current);
    mh->update_hoover ();

    if (m->input ().size ())
      m->treat ();

    while (!queue_->empty ())
    {
      (*(queue_->front ())) (this);
      queue_->pop ();
    }

    // time_ela = SDL_GetTicks () - current;
    current = SDL_GetTicks ();

    d->draw (s->map (), s->objmap (), interface, *s->disp ());

    // handling client position
    findid (tmpid);
    if (tmpid[0] != curid[0] || tmpid[1] != curid[1])
    {
      curid[0] = tmpid[0];
      curid[1] = tmpid[1];
      std::string res = "";
      res += curid[0];
      res += curid[1];
      s->nm ()->send (RType::UPDATE_POS, res);
    }

    // sending inputs to the server 10 times per sec
    if (SDL_GetTicks () - timer_input > 100)
      {
	timer_input = SDL_GetTicks ();
	if (obj_act_->size ())
	  {
	    for (std::map<int, ObjAction*>::iterator it = obj_act_->begin ();
		 it != obj_act_->end (); ++it)
	      {
		it->second->normalize ();
		Delta de (it->first, it->second->rotate (), it->second->move ());
		s->nm ()->send (RType::UPDATE_OBJ, de.tonet ());
		delete it->second;
		it->second = 0;
	      }
	    obj_act_->clear ();
	  }
      }
  }

  s->stop ();
  listen.detach ();

  delete w;
  delete mh;
  delete c;
  delete k;
  delete d;
  delete fps;
}

void
Main::build_menu ()
{
  Vector2d c_pos (0, 80);
  Vector2d c_size (100, 20);
  Container* container = new Container (c_pos, c_size);
  Button* button = new Button (Vector2d (0, 0), Vector2d (33, 100));
  Button* button2 = new Button (Vector2d (33, 0), Vector2d (33, 100));

  container->set_grid (3, 1);
  container->add_menu (button);
  container->add_menu (button2);
  button->activate ();
  button2->activate ();
  mh->add_menu (container, true);
  // chat = new Chat (c_pos, c_size, 50);
  // chat->size_max_set (Vector2d (1024, 768));
  // mh->add_menu (chat, true);
}

int main (int argc, char** argv)
{
  if (argc < 5)
  {
    std::cout << "Usage: " << argv[0] << "server@ port login password" << std::endl
	      << "server@: ip @ of the server or localhost" << std::endl;
    return 1;
  }

  Server s (argv[1], argv[2]);

  std::string logpwd = argv[3];
  logpwd += " ";
  logpwd += argv[4];

  if (!s.connect (logpwd))
    return 1;

  Main* m = new Main (argc, argv, &s);

  m->loop ();
}

void
Main::findid (unsigned char* p)
{
  Vector3f pos = c->pos ();

  unsigned char xid = pos (2) / 128;
  unsigned char yid = pos (1) / 128;

  p[0] = xid;
  p[1] = yid;
}
